package edu.bu.met683.TravelDroid;

import java.util.Calendar;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import edu.bu.met683.TravelDroid.data.DataUtilities;
import edu.bu.met683.TravelDroid.data.PointOfInterest;
import edu.bu.met683.TravelDroid.data.Stats;
import edu.bu.met683.TravelDroid.data.Tour;
import edu.bu.met683.TravelDroid.data.DataUtilities.TourState;

/**
 * This class implements the MapActivity that TravelDroid used to display Route,
 * Point Of Interest and Current Location data to the user.
 */
public class TravelDroidMapAndStats extends MapActivity {
	private static final String CLASS_TAG = TravelDroidMapAndStats.class
			.getSimpleName();
	private TravelDroidApplication application;

	// Menu Defs
	public static final int SATELLITE_MENU_ID = 10;
	public static final int SOUND_MENU_ID = 11;
	public static final int STATS_MENU_ID = 12;
	public static final int QUIT_MENU_ID = 13;
	public static final int UPLOAD_STATS_ID = 14;

	private static final String PAUSE = "Pause";
	private static final String START = "Start";
	private static final String CONTINUE = "Continue";
	private TourState tourState = TourState.STOPPED;
	private LocationListener locationListener;
	LocationManager locationManager = null;
	Handler statsHander;
	private Stats currentTourStats;

	// Map Controls
	MapView mapView;
	MapController controller;

	// The currently selected Tour
	private Tour currentTour;

	// Location Overlay
	MyLocationOverlay locationOverlay;

	boolean satDisplayed = false;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.v(CLASS_TAG, "onCreate() Called");
		super.onCreate(savedInstanceState);
		application = (TravelDroidApplication) this.getApplication();
		// Finish loading the map
		setContentView(R.layout.main);

		// Setup the Start and Stop buttons
		setupButtons();

		// Retrieve MapView and Controller
		mapView = (MapView) findViewById(R.id.mapview);
		controller = mapView.getController();

		initializeMap();

		application = (TravelDroidApplication) this.getApplication();
		currentTour = (Tour) application.GetCurrentTour();

		// Set a reference to the location manager
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

		// Add the currently selected Tour to the Map
		addTourToMap();

		currentTourStats = new Stats(currentTour.getLength());
		application.setCurrentTourStats(currentTourStats);
	}

	/**
	 * 
	 */
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, SATELLITE_MENU_ID, 0, "Toggle Satellite");
		menu.add(0, SOUND_MENU_ID, 0, "Toggle Sound");
		menu.add(0, STATS_MENU_ID, 0, "View Stats");
		menu.add(0, QUIT_MENU_ID, 0, "Quit Tour");
		menu.add(0, UPLOAD_STATS_ID, 0, "Upload Stats");
		return true;
	}

	/**
	 * Handles item selections
	 */
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case SATELLITE_MENU_ID:
			// Enable/Disable Satellite Imagery
			satDisplayed = !satDisplayed;
			mapView.setSatellite(satDisplayed);
			return true;
		case  UPLOAD_STATS_ID:
			 upload();
			 break;
		case QUIT_MENU_ID:
			finish();
			return true;
		case STATS_MENU_ID:
            String str = Stats.getEstimatedFinishTime(); 
            String str1 = Stats.getCurrentPace();
            String str2 = "nothing";
            String startTime = Stats.getStartTime();
            
            try {
                     str2 = Stats.getDistanceDisplay();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            new AlertDialog.Builder(this).setTitle("Distance")
            //.setMessage("Estimated Finish time: " + str +"\n" + "Pace: " + str1 +"\n" +"Distance covered: " + str2 +"\n" +"Start time: " + startTime + "\n" )
            .setMessage("Start time: " + startTime + "\n" + "Estimated Finish time: " + str +"\n" + "Pace: " + str1 +"\n" +"Distance covered: " + str2 +"\n")
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
            	{
            		public void onClick(DialogInterface di, int what) {
            			di.dismiss();
            		}
            	}).show();
            break;
		case SOUND_MENU_ID:
			application = (TravelDroidApplication) this.getApplication();
			application.setAudioOn(!application.isAudioOn());
			break;
		}
		return false;
	}

	public void upload()
	{
		
		Thread cThread = new Thread(new Client(currentTourStats.toString() ,"traveldroid.txt"));
        cThread.start();
        
	}
	/**
	 * Method used to initialize the MapView
	 */
	private void initializeMap() {
		Log.v(CLASS_TAG, "initializeMap() Called");

		// Enable Zoom View and set zoom
		mapView.setBuiltInZoomControls(true);
		controller.setZoom(18);

		// Disable Satellite
		mapView.setSatellite(satDisplayed);

		// Create overlay for Device Location and enable location updates
		locationOverlay = new MyLocationOverlay(this, this.mapView);
		mapView.getOverlays().add(locationOverlay);

		// Compass dosen't seem to be working
		// locationOverlay.enableCompass();

		// Method to run when Fix is acquired
		locationOverlay.runOnFirstFix(new Runnable() {
			public void run() {
				controller.animateTo(locationOverlay.getMyLocation());
			}
		});

	}

	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		UnregisterListeners();
	}
	
	@Override
	protected void onStop()
	{
		super.onStop();
		UnregisterListeners();
	}
	
	@Override
	protected void onResume() {
		Log.v(CLASS_TAG, "onResume() Called");
		super.onResume();

		// Create proximity alerts for the Tour
		DataUtilities.createProximityAlertsForTour(this, currentTour);

		// Enable Location Updates for MyLocationOverlay
		locationOverlay.enableMyLocation();
		if (tourState.equals(TourState.STARTED)
				|| tourState.equals(TourState.PAUSED))
			SetUpListeners();
	}

	@Override
	protected void onPause() {
		Log.v(CLASS_TAG, "onPause() Called");
		super.onPause();

		// Remove All Proximity Alerts
		DataUtilities.removeProximityAlertsForTour(this, currentTour);

		// Disable Location Updates for MyLocationOverlay
		locationOverlay.disableMyLocation();
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Adds the Points of Interest and the route overlay to the mapview.
	 */
	private void addTourToMap() {
		Log.v(CLASS_TAG, "addTourToMap() Called");

		// First add the points of interest
		List<PointOfInterest> pois = currentTour.getPoiList();

		// Overlay List
		List<Overlay> mapOverlays = mapView.getOverlays();
		Drawable drawable = this.getResources().getDrawable(
				R.drawable.mappin_red);
		POIItemizedOverlay itemizedOverlay = new POIItemizedOverlay(drawable,
				pois, this);

		// Save start point
		GeoPoint startPoint = null;

		// Create an overlay for each POI
		for (PointOfInterest poi : pois) {
			if (startPoint == null) {
				startPoint = poi.getPoint();
			}

			// Create Overlay for POI
			OverlayItem overlayitem = new OverlayItem(poi.getPoint(), poi
					.getName(), null);

			// Add the overlay item
			itemizedOverlay.addOverlay(overlayitem);
		}

		mapOverlays.add(itemizedOverlay);

		// move to location
		if (startPoint != null) {
			mapView.getController().animateTo(startPoint);
		}

		// Add the route to the map
		RouteOverlay routeOverlay = new RouteOverlay(currentTour
				.getRoutePoints());
		mapOverlays.add(routeOverlay);

		// redraw map
		mapView.postInvalidate();
	}

	/**
	 *  This method sets up the button handling for the Start Button
	 */
	private void setupButtons() 
	{
        final Button startPauseButton = (Button) findViewById(R.id.startPauseButton);        
        startPauseButton.setOnClickListener(new OnClickListener()
        {
        	public void onClick(View v)
        	{   
        		try
        		{
        			final Button startPauseButton = (Button) findViewById(R.id.startPauseButton);   
        			String buttonText = (String) startPauseButton.getText();

        			if(buttonText.equals(PAUSE) )
        			{
        				startPauseButton.setText(CONTINUE);
						DataUtilities.removeProximityAlertsForTour(v.getContext(), currentTour);
        				UnregisterListeners();
        			}
        			else if(buttonText.equals(CONTINUE))  //This is what starts the applicaiton!
        			{        				
        				startPauseButton.setText(PAUSE);
        				currentTourStats.setCurrentTime((Calendar)Calendar.getInstance());
        				DataUtilities.createProximityAlertsForTour(v.getContext(), currentTour);
        				SetUpListeners();
        			}
        			else if(buttonText.equals(START))
        			{
        				startPauseButton.setText(PAUSE);
        				currentTourStats.setCurrentTime((Calendar)Calendar.getInstance());
        				currentTourStats.getCurrentTime();
						currentTourStats.setStartTime((Calendar)(currentTourStats.getCurrentTime()).clone());
						DataUtilities.createProximityAlertsForTour(v.getContext(), currentTour);
        				SetUpListeners();        				
        			}
        		}
        		catch(Exception e)
        		{
        			Log.e("ERROR", "ERROR IN CODE TravelDroidMapAndStatsOnCLick:", e);
        		}
        	}
		});
	}

	private void SetUpListeners() {
		try {
			Criteria criteria = new Criteria();
			criteria.setAccuracy(Criteria.ACCURACY_FINE);
			criteria.setAltitudeRequired(false);
			criteria.setBearingRequired(false);
			criteria.setCostAllowed(true);
			criteria.setPowerRequirement(Criteria.POWER_LOW);

			String provider = locationManager.getBestProvider(criteria, true);
			locationListener = new LocationListener() {
				public void onLocationChanged(Location location) 
				{
					try
					{
						currentTourStats.updateStats(location);
					}
					catch(Exception ee)
					{
						Log.e("LocationListener", "error in onLocationChanged " + ee.getMessage());
					}
				}

				public void onProviderDisabled(String provider) {
				}

				public void onProviderEnabled(String provider) {
				}

				public void onStatusChanged(String provider, int status,
						Bundle extras) {
				}
			};
			locationManager.requestLocationUpdates(provider, 60000, 100,
					locationListener);
		} catch (Exception ee) {
			Log.e("MapActivity",
					"Error in TraveDroidMapAndStats.SetUpListeners ", ee);
		}
	}

	private void UnregisterListeners() {
		try {
			if (locationManager != null && (locationListener != null))
				this.locationManager.removeUpdates(locationListener);
		} catch (Exception ee) {
			Log.e("MapActivity", "error in UnregisterListeners ", ee);
		}
	}
}
